package fr.upmc.pstl.serializer;

import com.google.inject.Inject;
import com.google.inject.Provider;
import fr.upmc.pstl.definition.DefinitionPackage;
import fr.upmc.pstl.definition.Interval;
import fr.upmc.pstl.definition.Model;
import fr.upmc.pstl.definition.Spec;
import fr.upmc.pstl.definition.Type;
import fr.upmc.pstl.services.MyDslGrammarAccess;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.xtext.serializer.acceptor.ISemanticSequenceAcceptor;
import org.eclipse.xtext.serializer.acceptor.SequenceFeeder;
import org.eclipse.xtext.serializer.diagnostic.ISemanticSequencerDiagnosticProvider;
import org.eclipse.xtext.serializer.diagnostic.ISerializationDiagnostic.Acceptor;
import org.eclipse.xtext.serializer.sequencer.AbstractSemanticSequencer;
import org.eclipse.xtext.serializer.sequencer.GenericSequencer;
import org.eclipse.xtext.serializer.sequencer.ISemanticNodeProvider.INodesForEObjectProvider;
import org.eclipse.xtext.serializer.sequencer.ISemanticSequencer;
import org.eclipse.xtext.serializer.sequencer.ITransientValueService;
import org.eclipse.xtext.serializer.sequencer.ITransientValueService.ValueTransient;

@SuppressWarnings("restriction")
public class AbstractMyDslSemanticSequencer extends AbstractSemanticSequencer {

	@Inject
	protected MyDslGrammarAccess grammarAccess;
	
	@Inject
	protected ISemanticSequencerDiagnosticProvider diagnosticProvider;
	
	@Inject
	protected ITransientValueService transientValues;
	
	@Inject
	@GenericSequencer
	protected Provider<ISemanticSequencer> genericSequencerProvider;
	
	protected ISemanticSequencer genericSequencer;
	
	
	@Override
	public void init(ISemanticSequencer sequencer, ISemanticSequenceAcceptor sequenceAcceptor, Acceptor errorAcceptor) {
		super.init(sequencer, sequenceAcceptor, errorAcceptor);
		this.genericSequencer = genericSequencerProvider.get();
		this.genericSequencer.init(sequencer, sequenceAcceptor, errorAcceptor);
	}
	
	public void createSequence(EObject context, EObject semanticObject) {
		if(semanticObject.eClass().getEPackage() == DefinitionPackage.eINSTANCE) switch(semanticObject.eClass().getClassifierID()) {
			case DefinitionPackage.ENUM:
				if(context == grammarAccess.getEnumRule()) {
					sequence_Enum(context, (fr.upmc.pstl.definition.Enum) semanticObject); 
					return; 
				}
				else break;
			case DefinitionPackage.INTERVAL:
				if(context == grammarAccess.getIntervalRule()) {
					sequence_Interval(context, (Interval) semanticObject); 
					return; 
				}
				else break;
			case DefinitionPackage.MODEL:
				if(context == grammarAccess.getModelRule()) {
					sequence_Model(context, (Model) semanticObject); 
					return; 
				}
				else break;
			case DefinitionPackage.SPEC:
				if(context == grammarAccess.getSpecRule()) {
					sequence_Spec(context, (Spec) semanticObject); 
					return; 
				}
				else break;
			case DefinitionPackage.TYPE:
				if(context == grammarAccess.getTypeRule()) {
					sequence_Type(context, (Type) semanticObject); 
					return; 
				}
				else break;
			}
		if (errorAcceptor != null) errorAcceptor.accept(diagnosticProvider.createInvalidContextOrTypeDiagnostic(semanticObject, context));
	}
	
	/**
	 * Constraint:
	 *     {Enum}
	 */
	protected void sequence_Enum(EObject context, fr.upmc.pstl.definition.Enum semanticObject) {
		genericSequencer.createSequence(context, semanticObject);
	}
	
	
	/**
	 * Constraint:
	 *     (Min=INT Max=INT)
	 */
	protected void sequence_Interval(EObject context, Interval semanticObject) {
		if(errorAcceptor != null) {
			if(transientValues.isValueTransient(semanticObject, DefinitionPackage.Literals.INTERVAL__MIN) == ValueTransient.YES)
				errorAcceptor.accept(diagnosticProvider.createFeatureValueMissing(semanticObject, DefinitionPackage.Literals.INTERVAL__MIN));
			if(transientValues.isValueTransient(semanticObject, DefinitionPackage.Literals.INTERVAL__MAX) == ValueTransient.YES)
				errorAcceptor.accept(diagnosticProvider.createFeatureValueMissing(semanticObject, DefinitionPackage.Literals.INTERVAL__MAX));
		}
		INodesForEObjectProvider nodes = createNodeProvider(semanticObject);
		SequenceFeeder feeder = createSequencerFeeder(semanticObject, nodes);
		feeder.accept(grammarAccess.getIntervalAccess().getMinINTTerminalRuleCall_1_0_0(), semanticObject.getMin());
		feeder.accept(grammarAccess.getIntervalAccess().getMaxINTTerminalRuleCall_1_2_0(), semanticObject.getMax());
		feeder.finish();
	}
	
	
	/**
	 * Constraint:
	 *     elements+=Type*
	 */
	protected void sequence_Model(EObject context, Model semanticObject) {
		genericSequencer.createSequence(context, semanticObject);
	}
	
	
	/**
	 * Constraint:
	 *     (interval=Interval | enumeration=Enum)
	 */
	protected void sequence_Spec(EObject context, Spec semanticObject) {
		genericSequencer.createSequence(context, semanticObject);
	}
	
	
	/**
	 * Constraint:
	 *     (name=ID specification=Spec)
	 */
	protected void sequence_Type(EObject context, Type semanticObject) {
		if(errorAcceptor != null) {
			if(transientValues.isValueTransient(semanticObject, DefinitionPackage.Literals.TYPE__NAME) == ValueTransient.YES)
				errorAcceptor.accept(diagnosticProvider.createFeatureValueMissing(semanticObject, DefinitionPackage.Literals.TYPE__NAME));
			if(transientValues.isValueTransient(semanticObject, DefinitionPackage.Literals.TYPE__SPECIFICATION) == ValueTransient.YES)
				errorAcceptor.accept(diagnosticProvider.createFeatureValueMissing(semanticObject, DefinitionPackage.Literals.TYPE__SPECIFICATION));
		}
		INodesForEObjectProvider nodes = createNodeProvider(semanticObject);
		SequenceFeeder feeder = createSequencerFeeder(semanticObject, nodes);
		feeder.accept(grammarAccess.getTypeAccess().getNameIDTerminalRuleCall_1_0(), semanticObject.getName());
		feeder.accept(grammarAccess.getTypeAccess().getSpecificationSpecParserRuleCall_3_0(), semanticObject.getSpecification());
		feeder.finish();
	}
}
